Imports System.IO
Imports System.IO.Packaging
Imports org.codegen.common.ProgressIndicator

Public Class ZipFileCreator
    Implements IProgressable

    Public Event FileCompressionStart(ByVal sender As Object, ByVal e As ProgressableEventArgs) _
                Implements IProgressable.processStart

    Public Event FileCompressionProgress(ByVal sender As Object, ByVal e As ProgressableEventArgs) _
                    Implements IProgressable.processGoing

    Public Event FileCompressionFinished(ByVal sender As Object, ByVal e As ProgressableEventArgs) _
                    Implements IProgressable.processFinished

    Public Property wasCancelled As Boolean Implements IProgressable.wasCancelled

    Private Const BUFFER_SIZE As Long = 4096

    Public Sub AddFileToZip(ByVal zipFilename As String, ByVal fileToAdd As String)

        If File.Exists(zipFilename) Then File.Delete(zipFilename)

        Using zip As Package = System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate)

            Dim destFilename As String = ".\" & Path.GetFileName(fileToAdd)
            Dim uri As Uri = PackUriHelper.CreatePartUri(New Uri(destFilename, UriKind.Relative))

            If zip.PartExists(uri) Then
                zip.DeletePart(uri)
            End If

            Dim part As PackagePart = zip.CreatePart(uri, "", CompressionOption.Maximum)

            Using fileStream As New FileStream(fileToAdd, FileMode.Open, FileAccess.Read)

                Using dest As Stream = part.GetStream()
                    Dim lDestLength As Long = dest.Length

                    CopyStream(fileStream, dest)

                End Using

            End Using
        End Using

    End Sub


    Private Sub CopyStream(ByVal inputStream As System.IO.FileStream, _
                                  ByVal outputStream As System.IO.Stream)

        Dim bufferSize As Long = If(inputStream.Length < BUFFER_SIZE, inputStream.Length, BUFFER_SIZE)
        Dim buffer As Byte() = New Byte(CInt(bufferSize - 1)) {}
        Dim bytesRead As Integer = 0
        Dim bytesWritten As Long = 0
        Dim len As Long = inputStream.Length

        While (InlineAssignHelper(bytesRead, inputStream.Read(buffer, 0, buffer.Length))) <> 0

            outputStream.Write(buffer, 0, bytesRead)
            bytesWritten += bufferSize

            Dim peargs As ProgressableEventArgs = New ProgressableEventArgs(bytesWritten, len)
            RaiseEvent FileCompressionProgress(Me, peargs)
            If peargs.wasCancelled Then
                Me.wasCancelled = True
                Return
            End If

        End While

    End Sub

    Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
        target = value
        Return value
    End Function

    Public Sub startProcess() Implements IProgressable.startProcess

    End Sub

End Class
